#include "base.h"
#include <Geometry/AABB.h>

namespace shermit {
namespace lbvh {
#if enable_cuda

	template<class BVSOA_t>
	void LBvhLeaves<BVSOA_t>::allocateDevice(int size) {
		checkCudaErrors(GPUMalloc(parent, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(primIdx, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(segLen, sizeof(int) * size));
		checkCudaErrors(cudaMemset(segLen, 0, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(segOffset, sizeof(int) * size));
		//checkCudaErrors(GPUMalloc(escape, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(morton, sizeof(unsigned int) * size));
		bv.allocateDevice(size);
	}

	template<class BVSOA_t>
	void LBvhLeaves<BVSOA_t>::deallocateDevice() {
		checkCudaErrors(cudaFree(parent));
		checkCudaErrors(cudaFree(primIdx));
		checkCudaErrors(cudaFree(segLen));
		checkCudaErrors(cudaFree(segOffset));
		//checkCudaErrors(cudaFree(escape));
		checkCudaErrors(cudaFree(morton));
		bv.deallocateDevice();
	}

	template<class BVSOA_t>
	void LBvhInteriors<BVSOA_t>::allocateDevice(int size) {
		checkCudaErrors(GPUMalloc(parent, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(lc, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(rc, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(rangeL, sizeof(int) * size));
		checkCudaErrors(GPUMalloc(rangeR, sizeof(int) * size));
		bv.allocateDevice(size);
	}

	template<class BVSOA_t>
	void LBvhInteriors<BVSOA_t>::deallocateDevice() {
		checkCudaErrors(cudaFree(parent));
		checkCudaErrors(cudaFree(lc));
		checkCudaErrors(cudaFree(rc));
		checkCudaErrors(cudaFree(rangeL));
		checkCudaErrors(cudaFree(rangeR));
		bv.deallocateDevice();
	}

#endif

	template<class BVSOA_t>
	void LBvhLeaves<BVSOA_t>::allocateHost(int size) {
		parent = new int[size];
		primIdx = new int[size];
		segLen = new int[size];
		memset(segLen, 0, sizeof(int) * size);
		segOffset = new int[size];
		morton = new unsigned int[size];
		bv.allocateHost(size);
	}

	template<class BVSOA_t>
	void LBvhLeaves<BVSOA_t>::deallocateHost() {
		delete[] parent;
		delete[] primIdx;
		delete[] segLen;
		delete[] segOffset;
		delete[] morton;
		bv.deallocateHost();
	}

	template<class BVSOA_t>
	void LBvhInteriors<BVSOA_t>::allocateHost(int size) {
		parent = new int[size];
		lc = new int[size];
		rc = new int[size];
		rangeL = new int[size];
		rangeR = new int[size];
		bv.allocateHost(size);
	}

	template<class BVSOA_t>
	void LBvhInteriors<BVSOA_t>::deallocateHost() {
		delete[] parent;
		delete[] lc;
		delete[] rc;
		delete[] rangeL;
		delete[] rangeR;
		bv.deallocateHost();
	}

}
}